Skip to content

Publish the three hub pages as Markdown twins - #168

Merged
TommyBez merged 2 commits into
mainfrom
gtm/hub-md-twins
Aug 31, 2026
Merged

Publish the three hub pages as Markdown twins#168
TommyBez merged 2 commits into
mainfrom
gtm/hub-md-twins

Conversation

@TommyBez

@TommyBez TommyBez commented Aug 31, 2026

Copy link
Copy Markdown
Owner

What this changes

/resources.md, /compare.md, and /alternatives.md answered 404 in production while every page below them answered 200. This branch publishes the three hub pages as Markdown twins, following the conventions the comparison pages got in #165.

  • lib/seo/hubs.ts: the three hubs as content definitions, built from the same registries the HTML hubs render, so a page added to a registry appears in the hub twin with no change there. Each twin states what the hub indexes, then lists every page under it with the summary the hub card already shows, and the three hubs link to each other.
  • lib/markdown/twins.ts and lib/web-mcp-pages.ts: each hub is registered immediately above the collection it lists, so the twin registry and the WebMCP page catalogue read in the order an agent walks them.
  • next.config.ts: one content negotiation rule per hub, so /resources, /compare, and /alternatives answer in Markdown when the request sends Accept: text/markdown. The generic <path>.md rewrite already routed the three .md URLs, so only the Accept rules are new.
  • The three HTML pages now advertise <link rel="alternate" type="text/markdown"> through markdownTwinAlternates, the way every other page with a twin does.
  • public/llms.txt gains the alternatives hub and names the three hubs in the sentence that says which pages have a Markdown version.
  • The twins stay out of the sitemap. The sitemap lists the HTML page only, which is the existing convention for every twin on the site, and a test now asserts no .md URL is in it.

Hypothesis

The agent-facing graph had no hub nodes. An agent that arrived at /compare/claude-skills-vs-plugins.md, from llms.txt, from a citation, or by appending .md to a URL it was given, could read that page and nothing above it: the hub that lists the other three pairs answered 404 in Markdown. The descent from a hub to a page existed only in HTML, and the climb back did not exist at all.

Adding the hub twins closes the loop in both directions: from a hub twin an agent reaches every child, and from a child it can now climb to the hub, then across to the two sibling hubs. The claim being tested is that a complete Markdown graph gets more of the cluster read per visit than a set of disconnected leaf documents does.

Metric this should move

Server-side fetches of the three hub twins, and agent-facing coverage: the share of public content pages that answer in Markdown goes from every leaf to every leaf plus the three nodes above them. Secondary signal: fetches of child twins that arrive after a hub twin fetch from the same client, which is the descent the hub is there to enable.

No direct SEO metric. The twins are not in the sitemap, are not separate indexable documents, and the canonical URL in every twin header is the HTML page. Nothing here is expected to move impressions or clicks in Search Console.

How we will know it worked

At two to four weeks: 200 responses on /resources.md, /compare.md, and /alternatives.md in the server logs, from clients other than our own checks. Zero is the current baseline, since the three URLs answered 404 until this branch. If the hub twins are fetched but no child twin fetch follows from the same client, the hub is being read and the graph is still not being walked, which is a content problem in the hub twins rather than a routing one.

Verification

  • tsc --noEmit: 0 errors.
  • node --test tests/*.test.mjs: 561 pass, 0 fail. 10 of them are the new contract tests in tests/hub-markdown-twins.test.mjs: each hub has a twin at its own path plus .md, the twin links to every page the hub indexes and says what each one is about, the three hubs reach each other, the .md URL and the negotiated page URL return the same document through the route handler with and without the rewrite query, the negotiation rule exists, the HTML page advertises the alternate, WebMCP lists each hub above its own collection, llms.txt lists the three, and no .md URL is in the sitemap.
  • next build: exit 0.
  • Smoke on next start: /resources.md 200 (10628 bytes, 30 absolute links), /compare.md 200 (2352 bytes, 7 links), /alternatives.md 200 (1904 bytes, 7 links), all text/markdown; charset=utf-8. The same three paths without .md and with Accept: text/markdown answer 200 text/markdown, and answer HTML without the header. Non-regression: /compare/claude-skills-vs-plugins.md, /index.md, /codex-skills.md, /pricing.md, /llms.txt, and /sitemap.xml all still 200, /nope.md still 404, and the sitemap contains no .md URL.

Summary by CodeRabbit

  • New Features

    • Added Markdown versions of the Resources, Alternatives, and Comparisons hub pages.
    • Added navigation between hub pages and their related content.
    • Included the new Markdown pages in content negotiation and the site’s machine-readable index.
  • Bug Fixes

    • Improved canonical and alternate metadata consistency across hub pages.
  • Tests

    • Added coverage for rendering, metadata, navigation, API responses, ordering, and sitemap behavior.

/resources.md, /compare.md, and /alternatives.md answered 404 while every
page below them answered 200. An agent that reached
/compare/claude-skills-vs-plugins.md could read that page and nothing above
it: the descent from a hub to a page existed only in HTML, and there was no
climb back at all.

lib/seo/hubs.ts adds the three hubs as content definitions, built from the
same registries the HTML hubs render, so a page added to a registry appears
in the hub twin with no change there. Each twin states what the hub indexes
and then lists every page under it with the summary the hub card already
shows, and the three link to each other.

The twins follow the conventions the comparison pages got in #165: the
registry in lib/markdown/twins.ts, an entry in the WebMCP page catalogue,
the text/markdown alternate on the HTML page, and a content negotiation
rewrite so the page URL answers in Markdown when the request asks for it.
The generic <path>.md rewrite already routed the three URLs, so only the
Accept rules are new.

The twins stay out of the sitemap, which lists the HTML page only, and
llms.txt gains the alternatives hub and names the three hubs in the
sentence that says which pages have a Markdown version.
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
skillsboard Ready Ready Preview, v0 Aug 31, 2026 1:33pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 237ced37-fd0d-4738-ab1b-c72f6a4be6f7

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3e83bf92-795b-4a3f-bdd9-367fba855b42

📥 Commits

Reviewing files that changed from the base of the PR and between 0920b50 and 15786e6.

📒 Files selected for processing (10)
  • app/resources/page.tsx
  • lib/markdown/twins.ts
  • lib/seo/alternative-metadata.ts
  • lib/seo/compare-metadata.ts
  • lib/seo/hubs.ts
  • lib/web-mcp-pages.ts
  • next.config.ts
  • public/llms.txt
  • tests/hub-markdown-twins.test.mjs
  • tests/markdown-twins.test.mjs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

The change adds Markdown twins for the resources, alternatives, and comparison hubs. It derives hub content from shared registries, adds content-negotiation rewrites and alternate metadata, updates catalogues and llms.txt, and adds integration tests.

Changes

Markdown hub twins

Layer / File(s) Summary
Registry-backed hub definitions
lib/seo/hubs.ts
Adds shared definitions for the resources, alternatives, and comparison hubs. Each definition derives entries and dates from existing registries and includes related links.
Twin and catalogue registration
lib/markdown/twins.ts, lib/web-mcp-pages.ts, tests/markdown-twins.test.mjs
Registers each hub before its indexed collection in Markdown twin and WebMCP catalogues.
Routing and metadata integration
next.config.ts, app/resources/page.tsx, lib/seo/alternative-metadata.ts, lib/seo/compare-metadata.ts, public/llms.txt
Adds Markdown negotiation rewrites, Markdown alternate metadata, shared resources metadata, and hub links in llms.txt.
Hub twin integration tests
tests/hub-markdown-twins.test.mjs
Tests hub rendering, child links, negotiated responses, metadata, catalogue ordering, llms.txt, and sitemap behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 15786

This change adds Markdown representations for three existing public hub pages and keeps their HTML, sitemap, and related page behavior intact. No actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant NextConfig
  participant MarkdownAPI
  participant TwinRegistry
  Client->>NextConfig: Request hub with text/markdown
  NextConfig->>MarkdownAPI: Rewrite path to /api/markdown
  MarkdownAPI->>TwinRegistry: Resolve hub twin
  TwinRegistry-->>MarkdownAPI: Return Markdown document
  MarkdownAPI-->>Client: Return Markdown response
Loading

Poem

A rabbit hops through hubs of text
Three Markdown twins are neatly indexed
Registries gather links in line
Rewrites serve the pages fine
Tests thump softly: all paths align

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 9 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: publishing the three hub pages as Markdown twins.
Description check ✅ Passed The description explains the problem, implementation, expected impact, success metric, and detailed validation results. It uses headings that differ from the template and does not provide a separate I…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the problem, implementation, expected impact, success metric, and detailed validation results. It uses headings that differ from the template and does not provide a separate Impact section, but the required information is mostly present and the description is complete.

Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 9 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gtm/hub-md-twins

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T11:23:29.083724Z 15786e6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15786e68d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/seo/hubs.ts Outdated
modifiedAt: lastModified(resourceEntries),
intro: [
"This page is the index of the Skills Board resource pages: guides, skill format explainers, and reference pages for teams that share and operate AI skills. It answers nothing itself, and each entry below is the page that answers its own question.",
"Every page listed here names its publisher, its first-party sources, and the date its claims were last checked. Every one of them is also published as Markdown at the same URL with a `.md` suffix.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope the .md promise to pages that have twins

When an agent treats this sentence as routing guidance, two pages listed later in this document violate it: Related resources includes /about and /llms.txt, but neither is registered in twinEntries, so /about.md and /llms.txt.md fall through the generic rewrite to a 404. This makes the new hub advertise dead Markdown URLs; either restrict the promise to the indexed topic entries or publish/link actual twins for every listed page.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Founded. The sentence covered the whole document while the Related resources block links /about and /llms.txt, and neither has a twin: /about.md answers 404 in production, checked before the fix. Commit c2b3365 scopes the promise to the topic entries, which all carry twins, and adds a contract test that fails whenever a hub lists a page without a Markdown twin, for all three hubs. The /about and /llms.txt links stay in Related resources as plain links, now outside the promise. Typecheck 0, 562 tests green.

@TommyBez

Copy link
Copy Markdown
Owner Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

The intro sentence claimed every page listed on the hub is also published
as Markdown, but the Related resources block lists /about and /llms.txt,
and neither has a twin: /about.md answers 404 in production. The promise
now covers the topic entries, which all carry twins, and a new contract
test fails if a page ever appears in a hub list without one. The /about
link note also drops the pre repositioning wording.
@TommyBez
TommyBez merged commit 64362a1 into main Aug 31, 2026
4 checks passed
@TommyBez
TommyBez deleted the gtm/hub-md-twins branch August 31, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant